using System;
using System.Collections.Generic;
using System.Text;
using Index.PostingLists;
using Index.Dictionary;
using Index.Mapping;
using Index.Config;
using Coding;
using System.Reflection;

namespace Index
{
    public class WikiIndex
    {
        private IndexDictionary dict = null;
        private IDMapping document_mapping = null;
        private IndexConfiguration config = null;
        private CodingMethod coding_method = null;
        private IndexFile index_file = null;
        private string index_directory = null;
        private string wiki_directory = null;


        public WikiIndex(string index_directory, string wiki_directory)
        {
            this.index_directory = index_directory;
            this.wiki_directory = wiki_directory;
        }

        public void Open()
        {
            this.dict = IndexDictionary.DeSerialize(Path.GetDictionaryFilePath(index_directory));
            this.document_mapping = IDMapping.DeSerialize(Path.GetDocumentMappingFilePath(index_directory), true);
            this.config = IndexConfiguration.DeSerialize(Path.GetConfigFilePath(index_directory));

            Assembly bib = Assembly.Load("Coding");
            Type coding = bib.GetType(config.CodingMethod);
            this.coding_method = (CodingMethod)Activator.CreateInstance(coding);
            this.index_file = new IndexFile(Path.GetIndexFilePath(index_directory));

            this.index_file.Open();
        }

        public Object GetPostingList(string word)
        {

            if (this.dict.ContainsKey(word))
            {
                WordInfo info = this.dict[word];
                //Console.WriteLine("{0} {1}", info.StartAddr, info.EndAddr);

                byte[] tmp = index_file.ReadBytes(info.StartAddr, info.EndAddr);
              
                if (config.IndexType == IndexType.Positional)
                {
                    DocumentPositionList list =
                        new DocumentPositionList(tmp, coding_method, config.DocumentGaps);


                    return list;
                }

                if (config.IndexType == IndexType.Frequencial)
                {
                    DocumentFrequencyList list =
                        new DocumentFrequencyList(tmp, coding_method, config.DocumentGaps);

                    return list;
                }
                return null;
            }
            else
            {
                return null;
            }
        }

        public int CollectionFrequency(string word)
        {
            if (this.dict.ContainsKey(word))
            {
                return this.dict[word].Cf;
            }
            else
            {
                return 0;
            }
        }

        public int DocumentFrequency(string word)
        {
            if (this.dict.ContainsKey(word))
            {
                return this.dict[word].Df;
            }
            else
            {
                return 0;
            }
        }

        public IndexConfiguration Config
        {
            get
            {
                return config;
            }
        }
        
        public string GetURLToDocument(int document_id)
        {
            return Path.GetDocumentAbsoluteUrl(wiki_directory, this.document_mapping.GetWord(document_id));
        }

        public int N
        {
            get
            {
                return document_mapping.Count;
            }
        }
    }
}
